﻿using System;
using System.ComponentModel;
using System.Globalization;
using Microsoft.Xna.Framework;

namespace Phoenix.Xna.Framework
{
    /// <summary>
    /// Extends the functionality of System.Object instances.
    /// </summary>
    public static class ObjectExtensions
    {
        /// <summary>
        /// Conversion from object to an expected Type using all available TypeConverters and conversion techniques.
        /// </summary>
        /// <typeparam name="T">The type to convert this object to.</typeparam>
        /// <param name="obj">The extended object.</param>
        /// <returns>The object instance converted to the specified type.</returns>
        public static T TypeConvertionCast<T>(this object obj)
        {
            return (T)obj.TypeConvertionCast(typeof(T));
        }

        /// <summary>
        /// Conversion from object to an expected Type using all available TypeConverters and conversion techniques.
        /// </summary>
        /// <param name="obj">The extended object.</param>
        /// <param name="type">The type to convert this object to.</param>
        /// <returns>The object instance converted to the specified type.</returns>
        public static object TypeConvertionCast(this object obj, Type type)
        {
            object value = null;

            if (obj != null)
            {
                if (obj.GetType() == type)
                {
                    value = obj;
                }

                TypeConverter converter = TypeDescriptor.GetConverter(type);

                if (converter != null && converter.CanConvertFrom(obj.GetType()))
                {
                    // If custom converter is provided.
                    value = converter.ConvertFrom(obj);
                }
                else
                {
                    if (type.IsEnum)
                    {
                        value = Enum.Parse(type, obj.ToString());
                    }
                    else
                    {
                        // Otherwise, use CLR standard conversion.
                        if (type == typeof(string))
                        {
                            value = StringHelper.ObjectToString(obj);
                        }
                        else
                        {
                            value = Convert.ChangeType(obj, type, CultureInfo.InvariantCulture);
                        }
                    }
                }
            }

            return value;
        }
    }
}
